import requests
import os
from urllib.parse import urlparse
from pathlib import Path
from datetime import datetime, timedelta

def get_upload_policy(api_key, model_name):
    """获取文件上传凭证"""
    url = "https://dashscope.aliyuncs.com/api/v1/uploads"
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    params = {
        "action": "getPolicy",
        "model": model_name
    }
    
    response = requests.get(url, headers=headers, params=params)
    if response.status_code != 200:
        raise Exception(f"Failed to get upload policy: {response.text}")
    
    return response.json()['data']

def upload_file_to_oss(policy_data, file_path):
    """将文件上传到临时存储OSS"""
    file_name = Path(file_path).name
    key = f"{policy_data['upload_dir']}/{file_name}"
    
    with open(file_path, 'rb') as file:
        files = {
            'OSSAccessKeyId': (None, policy_data['oss_access_key_id']),
            'Signature': (None, policy_data['signature']),
            'policy': (None, policy_data['policy']),
            'x-oss-object-acl': (None, policy_data['x_oss_object_acl']),
            'x-oss-forbid-overwrite': (None, policy_data['x_oss_forbid_overwrite']),
            'key': (None, key),
            'success_action_status': (None, '200'),
            'file': (file_name, file)
        }
        
        response = requests.post(policy_data['upload_host'], files=files)
        if response.status_code != 200:
            raise Exception(f"Failed to upload file: {response.text}")
    
    return f"oss://{key}"

def upload_file_and_get_url(api_key, model_name, file_path):
    """上传文件并获取公网URL"""
    # 1. 获取上传凭证
    policy_data = get_upload_policy(api_key, model_name) 
    # 2. 上传文件到OSS
    oss_url = upload_file_to_oss(policy_data, file_path)
    
    return oss_url



class DouyinDownloader:
    """抖音视频下载器"""
    last_downloaded_filename = None
    
    def __init__(self):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
            'Referer': 'https://www.douyin.com/',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1'
        }
        
    def _get_filename_from_url(self, url):
        """从URL中提取文件名"""
        parsed = urlparse(url)
        path = parsed.path
        return os.path.basename(path) or 'douyin_video.mp4'
        
    def download(self, url, save_dir='.'):
        """
        下载抖音视频
        
        参数:
            url (str): 视频URL
            save_dir (str): 保存目录，默认为当前目录
        """
        try:
            if not os.path.exists(save_dir):
                os.makedirs(save_dir)
                
            filename = self._get_filename_from_url(url)
            save_path = os.path.join(save_dir, filename)
            
            print(f"开始下载: {url}")
            with requests.Session() as session:
                # 先发送HEAD请求获取信息
                head_resp = session.head(url, headers=self.headers, allow_redirects=True)
                head_resp.raise_for_status()
                
                # 正式下载
                response = session.get(url, headers=self.headers, stream=True, timeout=30)
                response.raise_for_status()
                
                # 获取文件大小
                file_size = int(response.headers.get('content-length', 0))
                print(f"文件大小: {file_size/1024/1024:.2f}MB")
                
                # 写入文件
                with open(save_path, 'wb') as f:
                    for chunk in response.iter_content(chunk_size=8192):
                        f.write(chunk)
                
                self.last_downloaded_filename = save_path
                print(f"视频已保存到: {os.path.abspath(save_path)}")
                return True
                
        except Exception as e:
            print(f"下载失败: {str(e)}")
            return False

if __name__ == "__main__":
    downloader = DouyinDownloader()
    
    # 获取用户输入
    video_url = input("请输入抖音分享内容: ").strip()
    if (downloader.download(video_url) is not True): 
        print("下载失败")
        exit()
        
    print(f"下载的文件: {downloader.last_downloaded_filename}")


    # 上传文件到OSS并获取公网URL
    # 待上传的文件路径
    file_path = downloader.last_downloaded_filename
    # 从环境变量中获取API Key 或者 在代码中设置 api_key = "your_api_key"
    api_key = os.getenv("DASHSCOPE_API_KEY")
    if not api_key:
        raise Exception("请设置DASHSCOPE_API_KEY环境变量")
        
    # 设置model名称
    model_name="paraformer-v2"
    try:
        public_url = upload_file_and_get_url(api_key, model_name, file_path)
        expire_time = datetime.now() + timedelta(hours=48)
        print(f"文件上传成功，有效期为48小时，过期时间: {expire_time.strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"公网URL: {public_url}")

    except Exception as e:
        print(f"Error: {str(e)}")

        